# 切片使用语法：[起始下标:结束下标:步长]，切片截取内容不包含结束下标对应的数据，步长指的是隔几个下标获取一个字符
# [star:end:step] step默认是1
a = 'hello python'
b= a  #把a字符串地址赋值给了b
#id()查看一个变量的内存地址
#print(id(a))    #2411251127600
#print(id(b))    #2411251127600

# 查找字符串find()和index()
# 两者都是返回字符串首次出现的索引，但是区别是没有查找到，find()返回-1，index()报错
# print(a.find('p'))  #6
# print(a.index('p'))  #6
# print(a.find('w'))  #-1
# print(a.index('w'))  #报错


# 切片 左闭右开，步长代表方向，负号为反方向
# print(a[2:7])   #llo p
# print(a[::-1])  #nohtyp olleh

# len()返回序列长度
# 列表，[],支持增删改查，列表中的元素改变的，单内存地址是不变的
# 各数据项用逗号分割，可以是任意类型的数据，支持切片
li =[1,2,3,'您好']
# print(len(li))   #4
# # 切片用法同上
# print(li*2)  #[1, 2, 3, '您好', 1, 2, 3, '您好']   相当于【复制】
# li.append(['p','d'])
# print(li)   #[1, 2, 3, '您好', ['p', 'd']]
# li.extend(['11',22,33]) 扩展等于批量增加
# print(li)[1, 2, 3, '您好', ['p', 'd'], '11', 22, 33]

# list()可强制转化为列表
# print(list(range(10)))   #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

'''
元组：与列表类似，不同之处是元组不能修改，
    元组使用的是小括号，也可以通过下标访问，
    可以是任何类型
    但是当元组只有一个元素时，要加入逗号
'''
# tuple1 = ('qw',)
# 但是元组内的列表是可以修改的
# tuple2 = tuple(range(10))   #强转换为tuple类型
# print(tuple2)   #(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
'''
cout(元素):统计元组中该元素的个数
index(元素):查找元素出现的索引
'''
# print(tuple2.count(8))    #1


'''
字典：类似于list，但是是由键值对组成，支持对数据的增删改查
    不是序列类型，没有下标概念，是无序的键值集合，是高级的数据类型
    用{}表示，键值对用逗号分隔
    键必须是不可变的类型【元组，字符串】，值可以是任意类型
    每个键必须是唯一的，值可以重复，如果存在重复的键，后者会覆盖前者
'''
# dict1 = {'name':'黄靛','age':'20','sex':'男','school':'南昌航空大学'}
# dict1['hoppy']= 'reading'   #新增
# print(dict1)   #{'name': '黄靛', 'age': '20', 'sex': '男', 'school': '南昌航空大学', 'hoppy': 'reading'}
# print(dict1['age'])   #20

# keys()获取键的集合，可迭代
# print(dict1.keys())  #dict_keys(['name', 'age', 'sex', 'school', 'hoppy'])
# values()获取键的集合，可迭代
# print(dict1.values())  #dict_values(['黄靛', '20', '男', '南昌航空大学', 'reading'])
# items()获取键，值的集合，可迭代
# print(dict1.items())  #dict_items([('name', '黄靛'), ('age', '20'), ('sex', '男'), ('school', '南昌航空大学'), ('hoppy', 'reading')])
# for key,value in dict1.items():
#     print('%s--%s'%(key,value))
'''
name--黄靛
age--20
sex--男
school--南昌航空大学
hoppy--reading
'''

'''
公用方法：
  合并操作+：两个对象相加操作，会合并两个对象，适用字符串，列表，元组
  复制操作*：对象自身按照指定次数进行+操作，适用字符串，列表，元组
  in判断元素是否存在：判断指定元素是否存在指定对象中，适用字符串，列表，元组，字典
'''
# str11 = 'python'
# print('o' in str11)  #true
dict11 = {'name':'张三'}
# print('name' in dict11) #true 默认判断key
#len(序列或字典) 获取元素的个数
# print(len(dict11))  #1

'''
函数的定义：
   def 函数名():
     函数体
     
函数的调用，在调用前必须先定义
   函数名()
'''
'''
必选参数：这个简单
默认参数（缺省参数）：
   定义的时候给参数赋值
   def fun(a= 6,b = 5):
可变参数：
   def fun(*arg):
   arg里面是存的参数元组
关键字可变参数：接受的参数必须是字典类型
   def fun(**kwargs):
混合：
   def fun(*args,**kwargs)
   可变参数必须放在关键字可变参数前
'''
# def fun1(*args):
#     '''
#     可变参数
#     :param args:
#     :return:
#     '''
#     sum = 0
#     for i in args:
#         # sum = sum + i;
#         pass
#     print(i)
#     pass
# fun1({'name':'9'})
# fun1(7,8,9,6,3,4)
# def fun2(**kwargs):
#     '''
#      关键字可变参数
#     :param kwargs: 必须是字典
#     :return:
#     '''
#     print(kwargs)
# dict111 = {'name':'hd','age':20}
# fun2(**dict111)   #{'name': 'hd', 'age': 20}
# fun2(name='hd',age=20)  #{'name': 'hd', 'age': 20}

# 自己玩的一个函数
# def f1(dict):
#     for key,value in dict.items():
#         if(len(value)>2):
#             dict[key] = value[:2]
#             pass
#         pass
#     return dict
# dict2 = {'name':'huangdian','son':['w','e','r']}
# print(f1(dict2))

'''
全局变量和局部变量
 作用域跟之前学的语言一样，
 如果想在局部作用域里修改全局变量，必须用global关键字声明
'''
# pro = '计算机科学与技术'
# def fun1_2():
#     global pro
#     pro = '人工智能'
# fun1_2()
# print(pro)  #人工智能

# 在python中万物皆对象
# python的参数引用传值，传递的是对象的引用

#python中的三元运算符：exp1 if contion else exp2
# print('条件1' if 3>2 else '条件2')  #条件1

'''
匿名函数：
语法：lambda 参数1,参数2,参数3:表达式
特点：使用lambda关键字去创建，没有名字的函数，
     匿名函数冒号后面的表达式有且只有一个
     匿名函数自带return，而return的结果就是表达式计算后的结果
'''
# M = lambda x,y:x+y
# print(M(2,3))  #5

# res = lambda x,y:x if x>y else y
# print(res(6,9)) #9

# python内置函数
'''
eval(expression[, globals[, locals]): eval() 函数用来执行一个字符串表达式，并返回表达式的值
  expression -- 表达式。
  globals -- 变量作用域，全局命名空间，如果被提供，则必须是一个字典对象。
  locals -- 变量作用域，局部命名空间，如果被提供，可以是任何映射对象。
'''
# print(eval('2+3'))   #5
# 也可执行函数
# def fun1_2():
#     print("函数执行了")
# eval('fun1_2()')   #函数执行了

'''
bin()：将十进制转化为二进制
hex()：将十进制转化为十六进制
list()：强制转化为列表
tuple()：强制转化为元组
dict()：创建一个对象  dict(name='hd',age=18,list=[1,2,3])
bytes()：转化为字节数组 bytes('我喜欢python',encoding='utf-8')
'''
'''
all(iterable)：用于判断给定的可迭代参数 iterable 中的所有元素是否都为 TRUE，如果是返回 True，否则返回 False。
   如果iterable的所有元素不为0、''、False或者iterable为空，all(iterable)返回True，否则返回False；
   注意：空元组、空列表返回值为True，这里要特别注意。
any()用于判断给定的可迭代参数 iterable 是否全部为 False，则返回 False，如果有一个为 True，则返回 True。
   元素除了是 0、空、FALSE 外都算 TRUE。如果都为空、0、false，则返回false，如果不都为空、0、false，则返回true。
'''
'''
sort()：只能用于list调用，直接修改原始对象，
  list.sort()
sorted() 可以对任意的可迭代对象进行排序，返回新的对象，而不是在原来的基础上进行操作
  sorted(iterable,reverse)
reverse():用于反向list元素,该方法没有返回值，是对list原始值进行修改
  list.reverse()
range()：用于生成一个整数列表
  range(star,stop,step)
split() 通过指定分隔符对字符串进行切片，如果参数 num 有指定值，则分隔 num+1 个子字符串
  str -- 分隔符，默认为所有的空字符，包括空格、换行(\n)、制表符(\t)等。
  num -- 分割次数。默认为 -1, 即分隔所有
  返回分割后的字符串列表。
'''
# print('s s t fd l'.split(' '))  #['s', 's', 't', 'fd', 'l']
# ui = zip([1,2,3],['a','e','h'])
# for i in ui:
#     print(i[0],i[1])
'''
1 a
2 e
3 h
'''
# for item in enumerate(['q','w','e']):
#     print(item)
'''
(0, 'q')
(1, 'w')
(2, 'e')
'''

#########################################
'''
set集合：也是python的一种数据类型，是无序且不重复的元素集合,不支持切片和索引
类似于字典，但只有key，没有value
创建集合：
  set1 = {1,2,3,4}
  或者 list = [1,2,3.4]
       set1 = set(list)
'''
# set1 = {1,2,3,4}
# set1.clear()
# print(set1)
# 集合的一些增删改查等操作查看文档


##########################################
# python的面向对象编程
class People:
    def eat(self):
        print("吃吃吃")
    def getId(self):
        print(id(self))

    def __init__(self,name,age,sex):
        '''
        实例属性的声明和初始化等工作
        在实例化对象时系统自动执行的
        类似于构造函数
        '''
        self.name = name
        self.age = age
        self.sex = sex
        print('__init__函数的执行')
    def __new__(cls, *args, **kwargs):
        '''
        创建并返回一个实例对象，调用一次就会返回一个实例对象，cls就是class的缩写
        在创建实例的过程中第一个被执行的函数，
        没有显性声明时，系统会自动返回实例对象
        :param args:
        :param kwargs:
        '''
        print('__new__函数的执行')
        return object.__new__(cls) #在这里真正的创建实例对象，当显性声明__init__方法后，必须返回实例对象

    def __str__(self):
        '''
        :return:打印对象的信息
        '''
        return "我是__str__返回的信息"


hd = People('黄靛',18,'男')


#################
#self的用法
'''
self和对象指向同一内存地址，可以认为self就是对象的引用
当某对象调用其方法时，python解释器会把这个对象作为第一个参数传给self，
所以我们只要传递后面的参数即可
'''

# 两者地址是相同的
# hd.getId()     #2337426902992
# print(id(hd))  #2337426902992

print(hd)  #我是__str__返回的信息
'''
__new__和__init__方法的区别
   __new__类的实例化方法，必须返回实例对象，否则对象创建不成功
   __init__方法是用来做数据属性的初始化工作，也可以认为是实例的构造方法
   __new__方法至少有一个参数是cls代表要实例化的类
   __new__的执行要早于__init__
'''